package com.googlecode.cpbi.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
 * @author Jeremy Wales
 */
public class FileUtils {
	private static final char PATH_SEPERATOR = '/';
	private static final Log LOG = LogFactory.getLog(FileUtils.class);
	private static final int EIGHT_KB = 8192;
	private static final ResourcePatternResolver RESOURCE_LOADER =
			new PathMatchingResourcePatternResolver(ClassLoaderUtils.getSystemClassLoader());

	private FileUtils() {
	}

	public static String getRelativePathOf(URL childResource, URL parentResource) {
		String rootPath = getPathOf(parentResource);
		String resourcePath = getPathOf(childResource);
		int jarUrlOffset =
				JarUtils.isJarUrl(childResource) && !JarUtils.isJarUrl(parentResource)
						? ResourceUtils.JAR_URL_SEPARATOR.length() : 0;
		return resourcePath.substring(resourcePath.indexOf(rootPath) + rootPath.length() + jarUrlOffset);
	}

	public static String getPathOf(URL resource) {
		String path = URLDecoder.decode(StringUtils.cleanPath(resource.getPath()));
		return com.googlecode.cpbi.util.StringUtils.trimLeading(PATH_SEPERATOR, path);
	}

	public static String getResourceNameOf(Class clazz) {
		return clazz.getName().replace('.', '/') + ".class";
	}

	public static Resource getResourceAt(String location) {
		return RESOURCE_LOADER.getResource(location);
	}

	public static Resource getResourceAt(URL location) {
		return getResourceAt(location.toString());
	}

	public static File getFileAt(String location) throws IOException {
		return getResourceAt(location).getFile();
	}

	public static File getFileAt(URL location) throws IOException {
		return getFileAt(location.toString());
	}

	public static InputStream getInputStreamFrom(URL location) throws IOException {
		return getInputStreamFrom(location.toString());
	}

	public static InputStream getInputStreamFrom(String location) throws IOException {
		return new BufferedInputStream(getResourceAt(location).getInputStream(), EIGHT_KB);
	}

	public static Resource[] getResourcesMatching(String locationPattern) throws IOException {
		return RESOURCE_LOADER.getResources(locationPattern);
	}

	public static void close(InputStream inputStream, URL location) {
		try {
			if (inputStream != null) inputStream.close();
		} catch (IOException e) {
			LOG.warn("Could not close input stream for '" + location + "'.", e);
		}
	}
}
